package com.ming.ex;

import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.security.sasl.AuthenticationException;
import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @Author 武汉尚学堂
 * 捕获全局异常
 * 1.不要把系统漏洞暴露给用户
 * 2.收集日志做分析 每隔2天看一下日志 分析哪个地方报错比较多 统一维护
 * logs-service 日志都要收集 放es
 * 使用mq  topic  异步记录日志  warn  info   error
 * 系统日志
 * sql日志
 * 报错日志
 * 比如运营人员 将一个轮播图下线了
 * 要记录修改之前的信息 方便做数据 回溯
 * 不要工程师维护
 */
@RestControllerAdvice
@Slf4j
public class WebErrorLog {

    /**
     * 认证异常
     *
     * @param e
     * @return
     */
    @ExceptionHandler(AuthenticationException.class)
    public ResponseEntity<String> authenticationExHandler(HttpServletRequest request, AuthenticationException e) {
        // 记录日志
        String ip = request.getRemoteHost();
        log.error("次ip:{}登录失败,原因是{}", ip, e.getMessage());
        return ResponseEntity.ok("登录失败，请重新登录");
    }

    /**
     * 运行时异常
     * 捕获自己以及子类的异常
     * 当异常处理器有具体异常的时候 就会被具体异常捕获
     *
     * @param e
     * @return
     */
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<String> runtimeExHandler(RuntimeException e) {
        // sql  报错了  存在注入的风险
        // 异常信息要收集
        log.error("运行时异常了{}", e.getMessage());
        return ResponseEntity.ok("系统正在维护中，请稍后再试！(#^.^#)");
    }

    // 参数异常

    /**
     * 方法参数校验异常
     *
     * @param bindException
     * @return
     */
    @ExceptionHandler({MethodArgumentNotValidException.class})
    public ResponseEntity<String> methodArgumentNotValidException(MethodArgumentNotValidException bindException) {
        BindingResult bindingResult = bindException.getBindingResult();
        System.out.println(bindingResult);
        StringBuilder sb = new StringBuilder("数据校验失败，原因是:");
        List<FieldError> fieldErrors = bindingResult.getFieldErrors();
        for (FieldError fieldError : fieldErrors) {
            sb.append("字段:" + fieldError.getField() + "," + fieldError.getDefaultMessage() + "!");
        }
        log.error("参数绑定失败{}", sb.toString());
        return ResponseEntity.ok("请求参数错误");
    }


}

